#!/usr/bin/env python
"""

    nice_numbers.py
    [--log_file PATH]
    [--verbose]

"""




################################################################################
#
#   nice_numbers
# 
#   Algorithm from 
#       Nice Numbers for Graph Labels              
#       by Paul Heckbert                           
#       from "Graphics Gems", Academic Press, 1990 
# 
#   Copyright (c) 2/22/2010 Leo Goodstadt
#   
#   Permission is hereby granted, free of charge, to any person obtaining a copy
#   of this software and associated documentation files (the "Software"), to deal
#   in the Software without restriction, including without limitation the rights
#   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#   copies of the Software, and to permit persons to whom the Software is
#   furnished to do so, subject to the following conditions:
#   
#   The above copyright notice and this permission notice shall be included in
#   all copies or substantial portions of the Software.
#   
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#   THE SOFTWARE.
#################################################################################

import sys, os
from collections import defaultdict
import math


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

#   Functions        


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
#_________________________________________________________________________________________
# 
#   nice_number
#_________________________________________________________________________________________
def nice_number (x, rounding = False):
    """
    returns nice rounded fraction
    """
    if x < 0:
        neg_num = True
        x = -x
    else:
        neg_num = False
    
    exponent_part = math.floor(math.log(x, 10))
    fraction_part = x / math.pow(10., exponent_part)
    if rounding:
        if fraction_part < 1.5:
            nf = 1.
        elif fraction_part < 3.:
            nf = 2.
        elif fraction_part < 7.:
            nf = 5.
        else:
            nf = 10.
    else:
        if fraction_part <=1.:
            nf = 1.
        elif fraction_part <=2.:
             nf = 2.
        elif fraction_part <=5.:
             nf = 5.
        else:
            nf = 10.
    
    if neg_num:
        return -nf * math.pow(10., exponent_part)
    return nf * math.pow(10., exponent_part)
    
    
    




def nice_label_numbers (min_value, max_value, numticks = 5):
    
    #expect min_value!=max_value
    range_values = nice_number(max_value - min_value, False)
    tick_mark_spacing = nice_number(range_values/(numticks - 1), 1)
    #graph range min_value and max_value
    graphmin = math.floor(min_value / tick_mark_spacing) * tick_mark_spacing;
    graphmax = math.ceil (max_value / tick_mark_spacing) * tick_mark_spacing;
    number_of_fractional_digits = max(-math.floor(math.log(tick_mark_spacing, 10)), 0)
    format_str = "%%.%df" % number_of_fractional_digits
    
    #print "graphmin=%g graphmax=%g increment=%g" % (graphmin, graphmax, tick_mark_spacing)
    
    numbers = []
    for i in xrange(20):
        x = graphmin + i * tick_mark_spacing
        if x >= graphmax + 0.5 * tick_mark_spacing:
            break
        numbers.append(x)
    else:
        raise Exception("Logic bug for min_value = %g, max_value = %g, numticks = %d)"
                            %(min_value, max_value, numticks))
    return numbers, format_str

    


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

#   Testing


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
import unittest
class Test_nice_numbers(unittest.TestCase):

    #       self.assertEqual(self.seq, range(10))
    #       self.assert_(element in self.seq)
    #       self.assertRaises(ValueError, random.sample, self.seq, 20)



    def test_function(self):
        """
            test 
        """

#
#   debug code not run if called as a module
#     
if __name__ == '__main__':
    if sys.argv.count("--debug"):
        sys.argv.remove("--debug")
    unittest.main()



    
